package com.alibaba.citrus.cr.sales.plan.facade.service;


import com.alibaba.citrus.cr.sales.plan.contants.SalesPlanConstants;
import com.alibaba.citrus.cr.sales.plan.sdo.SalesPlanSDO;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.bcorder.sales_plan.salesplandetail.dto.QuerySalesPlanDetailsByCustomerAddressIdRequest;
import com.epoch.app.bcorder.sales_plan.salesplandetail.dto.QuerySalesPlanDetailsByCustomerAddressIdResponse;
import com.epoch.app.bcorder.sales_plan.salesplandetail.dto.UpdateSalesPlanDetailsByCustomerAddressIdRequest;
import com.epoch.app.bcorder.sales_plan.salesplandetail.dto.UpdateSalesPlanDetailsByCustomerAddressIdResponse;
import com.epoch.app.bcorder.sales_plan.salesplandetail.model.SalesPlanDetail;
import com.epoch.app.bcorder.sales_plan.salesplandetail.service.SalesPlanDetailService;
import com.epoch.app.crplatformenhance.domain.customeraddress.dto.CustomerAddressFilterByDBRequest;
import com.epoch.app.crplatformenhance.domain.customeraddress.dto.CustomerAddressFilterByDBResponse;
import com.epoch.app.crplatformenhance.domain.customeraddress.service.CustomerAddressService;
import com.epoch.app.crplatformenhance.model.dto.CustomerAddressIndex;
import com.google.common.collect.Lists;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

;

/**
 * @author yifei
 * @since 2022/12/16
 */
@Service
public class SalesPlanLineDealService {
    private final Log log = Log.getLogger(SalesPlanLineDealService.class);

    @Resource
    private SalesPlanDetailService salesPlanDetailService;

    @Resource
    private CustomerAddressService customerAddressService;

    @Resource(name = "salesPlanTaskExecutor")
    private ThreadPoolTaskExecutor salesPlanTaskExecutor;

    /**
     * 更新月度计划明细销售负责人
     *
     * @param salesPlanSDO      月度计划主单
     */
    public Result<Boolean> updateManagerForSalesPlanDetail(SalesPlanSDO salesPlanSDO) {
        try {
            // 按照customerAddressId分组获取月度计划明细
            List<SalesPlanDetail> details = getSalesPlanDetails(salesPlanSDO);
            if (CollectionUtils.isEmpty(details)) {
                return Result.fail("OTS-02-006-00-16-022", "当前月度计划不存在月度计划明细");
            }

            // 获取当前月度计划明细中,客户送达方id对应的客户送达方列表
            List<CustomerAddressIndex> customerAddressIndexList = getCustomerAddressFilterResponse(details);
            // 未找到客户送达方无须更新
            if (CollectionUtils.isEmpty(customerAddressIndexList)) {
                log.info("SalesPlanLineDealService updateManagerForSalesPlanDetail customerAddress not found");
                return Result.success(Boolean.TRUE);
            }
            Map<String, CustomerAddressIndex> customerAddressMap = customerAddressIndexList.stream().collect(Collectors.toMap(index -> Objects.toString(index.getId(), null), a -> a, (a, b) -> a));

            List<Future<Integer>> futureList = Lists.newArrayList();
            for (SalesPlanDetail detail : details) {
                CustomerAddressIndex customerAddress = customerAddressMap.get(detail.getCustomerAddressId());
                if (Objects.isNull(customerAddress) || StringUtils.isBlank(customerAddress.getPrincipal())) {
                    // 未找到对应的客户送达方信息,无需更新
                    log.warn("SalesPlanLineDealService updateManagerForSalesPlanDetail customerAddress not found:{}", detail.getCustomerAddressId());
                    continue;
                }
                // 该送达方的客户负责人未变更，无需更新
                if (customerAddress.getPrincipal().equals(detail.getManageEmployeeId())) {
                    continue;
                }
                try {
                    CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {
                        return updateSalesPlanDetails(detail.getPlanId(), customerAddress);
                    }, salesPlanTaskExecutor);
                    futureList.add(completableFuture);
                } catch (Exception e) {
                    log.error("SalesPlanLineDealService updateManagerForSalesPlanDetail error planId:{}, customerAddressId:{}", salesPlanSDO.getId(), detail.getCustomerAddressId());
                    return Result.fail("OTS-02-006-00-16-023","更新销售负责人失败,请稍后重试");
                }
            }
            try {
                for (Future<Integer> future : futureList) {
                    future.get(3, TimeUnit.SECONDS);
                }
            } catch (Exception e) {
                log.error("SalesPlanLineDealService updateSalesPlanDetails consume time long");
            }
        } catch (Exception e) {
            log.error("SalesPlanLineDealService updateManagerForSalesPlanDetail occur exception:", e);
            return Result.fail("OTS-02-006-00-16-023","更新销售负责人失败,请稍后重试");
        }
        return Result.success(Boolean.TRUE);
    }

    /**
     * 获取对应月度计划主单的月度计划明细
     *
     * @param salesPlanSDO 月度计划主单
     * @return 月度计划明细
     */
    private List<SalesPlanDetail> getSalesPlanDetails(SalesPlanSDO salesPlanSDO) {
        QuerySalesPlanDetailsByCustomerAddressIdRequest request = new QuerySalesPlanDetailsByCustomerAddressIdRequest();
        request.setPlanId(salesPlanSDO.getId());
        request.setStart(SalesPlanConstants.START);
        request.setLimit(SalesPlanConstants.LIMIT);
        QuerySalesPlanDetailsByCustomerAddressIdResponse salesPlanDetailResponse = salesPlanDetailService.querySalesPlanDetailsByCustomerAddressId(request);
        if (Objects.isNull(salesPlanDetailResponse) || salesPlanDetailResponse.getTotal() == 0) {
            return null;
        }
        List<SalesPlanDetail> salesPlanDetailList = Lists.newArrayList();
        // 需要全量捞出对应月度计划的所有子单,因此需要计算分页参数
        int totalPage = salesPlanDetailResponse.getTotal() % SalesPlanConstants.LIMIT == 0 ? salesPlanDetailResponse.getTotal() / SalesPlanConstants.LIMIT : (salesPlanDetailResponse.getTotal() / SalesPlanConstants.LIMIT) + 1;
        for (int i = 0; i < totalPage; i++) {
            request.setStart(SalesPlanConstants.LIMIT * i);
            request.setLimit(SalesPlanConstants.LIMIT);
            QuerySalesPlanDetailsByCustomerAddressIdResponse salesPlanDetails = salesPlanDetailService.querySalesPlanDetailsByCustomerAddressId(request);
            if (Objects.isNull(salesPlanDetails) || salesPlanDetails.getTotal() == 0 || CollectionUtils.isEmpty(salesPlanDetails.getResult())) {
                continue;
            }
            salesPlanDetailList.addAll(salesPlanDetails.getResult());
        }
        return salesPlanDetailList;
    }

    /**
     * 获取月度计划明细客户送达方列表
     *
     * @param details 月度计划明细
     * @return 客户送达方列表
     */
    private List<CustomerAddressIndex> getCustomerAddressFilterResponse(List<SalesPlanDetail> details) {
        List<CustomerAddressIndex> customerAddressIndexList = Lists.newArrayList();
        for (List<SalesPlanDetail> list : Lists.partition(details, SalesPlanConstants.LIMIT)) {
            Set<String> customerAddressSet = list.stream().map(SalesPlanDetail::getCustomerAddress).collect(Collectors.toSet());
            Set<String> customerAddressIdSet = list.stream().map(SalesPlanDetail::getCustomerAddressId).filter(StringUtils::isNotBlank).collect(Collectors.toSet());
            if (CollectionUtils.isEmpty(customerAddressSet) && CollectionUtils.isEmpty(customerAddressIdSet)) {
                return null;
            }
            // 批量查询客户地址(条件:status=1 启用)
            // 月度计划中参与送达方最多不会超过500个，limit=1000已满足需求
            CustomerAddressFilterByDBRequest addressRequest = new CustomerAddressFilterByDBRequest();
            addressRequest.setStart(0);
            addressRequest.setStatus(1);
            addressRequest.setLimit(1000);
            addressRequest.setAddressCodeList(Lists.newArrayList(customerAddressSet));
            addressRequest.setIdList(Lists.newArrayList(customerAddressIdSet));
            log.info("SalesPlanLineDealService customerAddressFilterByDB request:{}", JSONObject.toJSONString(addressRequest));
            CustomerAddressFilterByDBResponse response = customerAddressService.customerAddressFilterByDB(addressRequest);
            if (Objects.isNull(response) || CollectionUtils.isEmpty(response.getResult())) {
                continue;
            }
            customerAddressIndexList.addAll(response.getResult());
        }
        return customerAddressIndexList;
    }

    /**
     * 通过月度计划id和客户送达方id,更新对应月度计划明细的送达方信息
     *
     * @param planId    月度计划id
     * @param customerAddress 送达方信息
     * @return 结果
     */
    private Integer updateSalesPlanDetails(Long planId, CustomerAddressIndex customerAddress) {
        UpdateSalesPlanDetailsByCustomerAddressIdRequest request = new UpdateSalesPlanDetailsByCustomerAddressIdRequest();
        request.setPlanId(planId);
        request.setChannelCode(customerAddress.getChannelCode());
        request.setOrgBusinessUnitCode(customerAddress.getOrgBussinessUnitCode());
        request.setOrgSalesOrganizationCode(customerAddress.getOrgSaleOrganizationCode());
        request.setOrgSalesChannelCode(customerAddress.getOrgSaleChannelCode());
        request.setOrgSalesDepartmentCode(customerAddress.getOrgSaleDepartmentCode());
        request.setCustomerCode(customerAddress.getCustomerCode());
        request.setCustomerAddress(customerAddress.getAddressCode());
        request.setCustomerAddressId(Objects.toString(customerAddress.getId(), null));
        request.setManageEmployeeId(customerAddress.getPrincipal());
        UpdateSalesPlanDetailsByCustomerAddressIdResponse response = salesPlanDetailService.updateSalesPlanDetailsByCustomerAddressId(request);
        return response.getCount();
    }
}
